package net.ossrs.yasea.demo;

import android.app.Application;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.os.Environment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.RelativeLayout;
import android.view.WindowManager.LayoutParams;
import android.widget.Toast;

import com.anyun.thirdparty.CameraID;
import com.anyun.thirdparty.MediaArgu;
import com.anyun.thirdparty.TerminalApp;
import com.anyun.thirdparty.shell.UsbCameraMgr;
import com.github.faucamp.simplertmp.RtmpHandler;

import net.ossrs.yasea.SrsCameraView;
import net.ossrs.yasea.SrsEncodeHandler;
import net.ossrs.yasea.SrsPublisher;
import net.ossrs.yasea.SrsRecordHandler;

import java.io.IOException;
import java.net.SocketException;
import java.util.concurrent.TimeUnit;

import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;


public class LiveVideoManager implements RtmpHandler.RtmpListener, SrsRecordHandler.SrsRecordListener, SrsEncodeHandler.SrsEncodeListener {
    private final String TAG = "LiveVideoManager";
    private WindowManager windowManager;
    private LayoutParams wmParams;
    private RelativeLayout floatLayout;
    private Disposable startDisposable,stopDisposable,videoRecordDisposable;
    private SrsCameraView cameraPreview;
    private String rtmpUrl = "rtmp://ossrs.net/wbr/sb43x";
    private boolean pushFlag = false;//标记是否已经开推流 true已经开启；；；之所以有这个标志位是因为开启录像时需提前开启推流，否则录不起
    private boolean isRecording= false;//标记是否正在录像 true正在录像
    private boolean isFirst = true;//标记悬浮窗是否第一次初始，不是的话后续只要add
    private SrsPublisher mPublisher;//控制推流 与 录像
    private String recPath = Environment.getExternalStorageDirectory().getPath()+"/123.mp4" ;//存放mp4录制视频的目录
    private MediaArgu media;
    private LiveListener liveListener;

    public String getRtmpUrl() {
        return rtmpUrl;
    }

    public void setRtmpUrl(String rtmpUrl) {
        this.rtmpUrl = rtmpUrl;
    }

    private static final LiveVideoManager ourInstance = new LiveVideoManager();

    public static LiveVideoManager getInstance() {
        return ourInstance;
    }
    private   int x,y;//touch的坐标

    /**
     * 检查是否客户端传进来参数，
     * @return true-传进来了 fasle-没传
     */
    private boolean checkMediaArgsNotNull(){
        if (media == null){
            return false;
        }else{
            return true;
        }

    }

    private LiveVideoManager() {

    }

    /**
     * client传过来的参数
     * @param mediaArgu
     */
    public void transferArgs(MediaArgu mediaArgu){
        //如果要传参，请先于start启动前 传参
        Log.i(TAG, "transferArgs: "+mediaArgu);
        this.media = mediaArgu;
    }
    public void initLive(){
        Log.i(TAG, "初始化Yasea Sdk");
        if (checkMediaArgsNotNull()){
            if (media.getCameraId() == CameraID.USB_CAMERA_ID1){
                UsbCameraMgr.getInstance().init();
            }
        }else{
            Log.i(TAG, "内部摄像头，直接使用");
            initView();
        }

        initPublisher();

    }

    public void setListener(LiveListener listener){
        this.liveListener = listener;
    }

    /**
     * 开始录像
     */
    public void startRecord(){
        if (!checkFloatingWindow()){
            windowManager.addView(floatLayout,wmParams);
            mPublisher.startCamera();
        }
        if (pushFlag){
            cancleStartDelay();
            //延迟1s  是因为录像跟推流一起开的话，先推一会才能录
            startDisposable = Observable.timer(1,TimeUnit.SECONDS)
                    .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
                    .doOnNext(new Consumer<Long>() {
                        @Override
                        public void accept(Long aLong) throws Exception {
                            Log.i(TAG, "accept: 开始录像(推流需要提前开始）,否则会出错");
                            isRecording = true;
                            mPublisher.startRecord(recPath);
                        }
                    }).subscribe();
        }else{
            throw new RuntimeException("please firstly call startLive() method .");
        }



    }
    private void initPublisher() {
        if (checkUseUsbCamera()){
            LayoutInflater inflater = LayoutInflater.from(TerminalApp.getInstance());
            //获取悬浮窗所在布局
            cameraPreview = ((RelativeLayout) inflater.inflate(R.layout.view_live,null)).findViewById(R.id.srsCameraView);
        }
        mPublisher = new SrsPublisher(cameraPreview);
        mPublisher.setEncodeHandler(new SrsEncodeHandler(this));
        mPublisher.setRtmpHandler(new RtmpHandler(this));
        mPublisher.setRecordHandler(new SrsRecordHandler(this));
        if (checkMediaArgsNotNull()){
            //TODO 先写死
            mPublisher.setPreviewResolution(640, 480);
            mPublisher.setOutputResolution(640, 480);
        }else{
            mPublisher.setPreviewResolution(320, 240);
            mPublisher.setOutputResolution(320, 240);
        }

        mPublisher.setScreenOrientation(Configuration.ORIENTATION_LANDSCAPE);
        mPublisher.setVideoSmoothMode();
        if (checkUseUsbCamera()){
            UsbCameraMgr.getInstance().startUsbCamera();
            mPublisher.setUseUsbCamera(UsbCameraMgr.getInstance().getUsbCamera());
            mPublisher.setSurfaceHodler(UsbCameraMgr.getInstance().getSurfaceHolder());
        }else{
            mPublisher.startCamera();
        }

    }

    /**
     * 检查是否使用外接UsbCamera
     * @return true-外接USbCamera false-内置伸向头
     */
    private boolean checkUseUsbCamera() {
        if(checkMediaArgsNotNull()){
            if (media.getCameraId() == CameraID.USB_CAMERA_ID1){
                return true;
            }else{
                return false;
            }
        }else{
            return true;
        }
    }


    private void cancleStartDelay() {
        if (startDisposable!=null && startDisposable.isDisposed()){
            startDisposable.dispose();
            startDisposable = null;
            Log.i(TAG, "cancleStartDelay: ");
        }
    }


    /**
     * 创建悬浮窗 并在悬浮窗设置Touch事件
     */
    private void createFloatWindow() {
        wmParams = new LayoutParams();
        windowManager = (WindowManager) TerminalApp.getInstance().getSystemService(Application.WINDOW_SERVICE);
        //设置windowType
        wmParams.type = LayoutParams.TYPE_PHONE;
        //设置图片格式，效果为背景透明
        wmParams.format = PixelFormat.RGBA_8888;
        //设置悬浮窗口不可聚焦
        wmParams.flags = LayoutParams.FLAG_NOT_FOCUSABLE;
        //调整悬浮窗显示的位置为右下
//        wmParams.gravity = Gravity.RIGHT | Gravity.BOTTOM;
        //以屏幕右下角为原点，设置x,y初始值，相对于gravity
        wmParams.x = 300;
        wmParams.y = 300;
        //设置悬浮窗口长度和宽度
        wmParams.width = 120;
        wmParams.height = 90;

        LayoutInflater inflater = LayoutInflater.from(TerminalApp.getInstance());
        //获取悬浮窗所在布局
        floatLayout = (RelativeLayout) inflater.inflate(R.layout.view_live,null);
        windowManager.addView(floatLayout,wmParams);

        floatLayout.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {



                switch (motionEvent.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        x = (int) motionEvent.getRawX();
                        y = (int) motionEvent.getRawY();
                        break;
                    case MotionEvent.ACTION_MOVE:
                        int nowX = (int) motionEvent.getRawX();
                        int nowY = (int) motionEvent.getRawY();
                        int movedX = nowX - x;
                        int moveY = nowY - y;
                        x = nowX;
                        y = nowY;
                        wmParams.x = wmParams.x + movedX;
                        wmParams.y = wmParams.y + moveY;
                        windowManager.updateViewLayout(floatLayout, wmParams);
                        break;
                    case MotionEvent.ACTION_UP:
                        break;
                    default:
                        Log.i(TAG, "onTouch: " + motionEvent.getAction());
                        break;
                }



                return false;  //此处必须返回false，否则OnClickListener获取不到监听
            }
        });
    }

    private void initView(){
        if (floatLayout!= null &&cameraPreview == null){
            Log.i(TAG, "initView: floatLayout!= null &&cameraPreview == null");
        cameraPreview = (SrsCameraView)floatLayout.findViewById(R.id.srsCameraView);
        }else {
            if (cameraPreview!=null){

            }else{
                Log.i(TAG, "initView: 加载floatLayout");
                createFloatWindow();
                cameraPreview = (SrsCameraView)floatLayout.findViewById(R.id.srsCameraView);
            }

        }


    }

    /**
     * 开启RTMP推流直播
     */
    public void startLive(){

        Log.i(TAG, " YunNan开始推流");
        mPublisher.startPublish(rtmpUrl);
        if (liveListener != null){
            liveListener.rtmpAddress(rtmpUrl);
        }
        if(checkUseUsbCamera()){

        }else{

            mPublisher.startCamera();
        }
        pushFlag = true;

    }

    private boolean checkFloatingWindow() {
        return isFirst;
    }

    /**
     * 停掉推流
     */
    public void stopLive(){
        stopLiveDelay(1);
    }

    /**
     * 停止录像
     */
    public void stopRecord(){
        isRecording = false;
        mPublisher.stopRecord();
        if (!pushFlag){
            mPublisher.stopCamera();
//            removeFloatingWindow();
        }else{

        }
    }
    private void stopLiveDelay(int delay){
        cancleStop();
        if (!pushFlag){
            throw new RuntimeException("没有启动过推流");
        }else{
            stopDisposable = Observable.timer(delay,TimeUnit.SECONDS)
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .doOnNext(new Consumer<Long>() {
                        @Override
                        public void accept(Long aLong) throws Exception {
                            Log.i(TAG, "YunNan停止录像和推流");
                            mPublisher.stopPublish();


                            if (checkUseUsbCamera()){
                                Log.i(TAG, "使用的外接usbCamera 关闭");
                                UsbCameraMgr.getInstance().stopUsbCamera();
                                mPublisher.setUseUsbCamera(null);//需要设置为null 停止预览
                            }else{

                                mPublisher.stopCamera();
                            }

                            if (checkUseUsbCamera()){
                                UsbCameraMgr.getInstance().removeFloatView();
                            }
//                            removeFloatingWindow();

                            pushFlag = false;
//                        stopRecord();//推流结束的时候录像也结束了 ，录像结束的时候，推流可以继续推

                        }
                    })
                    .subscribe();
        }

    }

    private void removeFloatingWindow() {
        //移除悬浮窗
        if (windowManager != null && floatLayout!=null){
            try{
                windowManager.removeViewImmediate(floatLayout);
                isFirst = false;

            }catch (Exception e){

            }
        }
    }

    private void cancleStop() {
        if (stopDisposable != null && !stopDisposable.isDisposed()){
            stopDisposable.dispose();
            stopDisposable = null;
        }
    }

    @Override
    public void onRtmpConnecting(String msg) {
        Toast.makeText(TerminalApp.getInstance(), msg, Toast.LENGTH_SHORT).show();
        Log.i(TAG, "onRtmpConnecting: ");
    }

    @Override
    public void onRtmpConnected(String msg) {
//        Toast.makeText(TerminalApp.getInstance(), msg, Toast.LENGTH_SHORT).show();
        Log.i(TAG, "onRtmpConnected: ");
        if (liveListener != null){
            liveListener.onRtmpConnected();
        }



    }

    @Override
    public void onRtmpVideoStreaming() {

    }

    @Override
    public void onRtmpAudioStreaming() {

    }

    @Override
    public void onRtmpStopped() {
        Log.i(TAG, "onRtmpStopped: ");
        if (liveListener != null){
            liveListener.onRtmpStopped();
        }
    }

    @Override
    public void onRtmpDisconnected() {
        Log.i(TAG, "onRtmpDisconnected: ");
        if (liveListener != null){
            liveListener.onRtmpDisconnected();
        }
    }

    @Override
    public void onRtmpVideoFpsChanged(double fps) {
        Log.i(TAG, "onRtmpVideoFpsChanged: ");
    }

    @Override
    public void onRtmpVideoBitrateChanged(double bitrate) {
        Log.i(TAG, "onRtmpVideoBitrateChanged: ");
    }

    @Override
    public void onRtmpAudioBitrateChanged(double bitrate) {
        Log.i(TAG, "onRtmpAudioBitrateChanged: ");
    }

    @Override
    public void onRtmpSocketException(SocketException e) {
        Log.i(TAG, "onRtmpSocketException: ");
    }

    @Override
    public void onRtmpIOException(IOException e) {
        Log.i(TAG, "onRtmpIOException: ");
    }

    @Override
    public void onRtmpIllegalArgumentException(IllegalArgumentException e) {
        Log.i(TAG, "onRtmpIllegalArgumentException: ");
    }

    @Override
    public void onRtmpIllegalStateException(IllegalStateException e) {
        Log.i(TAG, "onRtmpIllegalStateException: ");
    }

    @Override
    public void onRecordPause() {
        Log.i(TAG, "onRecordPause: ");
    }

    @Override
    public void onRecordResume() {
        Log.i(TAG, "onRecordResume: ");
    }

    @Override
    public void onRecordStarted(String msg) {
        Toast.makeText(TerminalApp.getInstance(), msg, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onRecordFinished(String msg) {
        Toast.makeText(TerminalApp.getInstance(), msg, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onRecordIllegalArgumentException(IllegalArgumentException e) {

    }

    @Override
    public void onRecordIOException(IOException e) {
        Log.i(TAG, "onRecordIOException: ");
    }

    @Override
    public void onNetworkWeak() {
        if (liveListener != null){
            liveListener.onNetworkWeak();
        }
    }

    @Override
    public void onNetworkResume() {
        Toast.makeText(TerminalApp.getInstance(), "NetWork resume", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onEncodeIllegalArgumentException(IllegalArgumentException e) {
        Toast.makeText(TerminalApp.getInstance(), e.getMessage(), Toast.LENGTH_SHORT).show();

    }


    public void stopFloatWindow() {
        removeFloatingWindow();

    }

    public interface LiveListener{
        /**网络环境差，请检查网络***/
        public void onNetworkWeak();
        public void onRtmpDisconnected();
        /**开始推流**/
        public void onRtmpConnected();
        /**停止推流**/
        public void onRtmpStopped();
        void rtmpAddress(String url);
    }

}
